package com.aura.springbook.common.util;

import com.aura.springbook.common.R;
import com.aura.springbook.common.constant.BookConstants;
import com.aura.springbook.common.util.ResponseUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页工具类
 */
public class PageUtil {

    /**
     * 转换分页对象
     * <p>
     * 将一种类型的分页对象转换为另一种类型的分页对象
     * 通常用于将数据库实体转换为VO对象
     *
     * @param sourcePage 源分页对象
     * @param converter  转换函数
     * @param <T>        源类型
     * @param <R>        目标类型
     * @return 转换后的分页对象
     */
    public static <T, R> IPage<R> convert(IPage<T> sourcePage, Function<T, R> converter) {
        IPage<R> targetPage = new Page<>(sourcePage.getCurrent(), sourcePage.getSize(), sourcePage.getTotal());
        List<R> targetRecords = sourcePage.getRecords().stream()
                .map(converter)
                .collect(Collectors.toList());
        targetPage.setRecords(targetRecords);
        targetPage.setPages(sourcePage.getPages());
        return targetPage;
    }

    /**
     * 验证分页参数
     * <p>
     * 检查页码和每页大小是否在合理范围内
     * 页码必须大于0，每页大小必须大于0且不超过最大限制
     *
     * @param page 页码
     * @param size 每页大小
     * @return 是否有效
     */
    public static boolean validatePageParams(int page, int size) {
        return page > 0 && size > 0 && size <= BookConstants.MAX_PAGE_SIZE; // 使用常量限制每页最大记录数
    }

    /**
     * 获取默认页码
     * <p>
     * 如果页码无效则返回默认页码
     *
     * @param page 页码
     * @return 有效页码
     */
    public static int getDefaultPage(int page) {
        return page > 0 ? page : BookConstants.DEFAULT_PAGE;
    }

    /**
     * 获取默认每页大小
     * <p>
     * 如果每页大小无效则返回默认值，且不超过最大限制
     *
     * @param size 每页大小
     * @return 有效每页大小
     */
    public static int getDefaultSize(int size) {
        return size > 0 && size <= BookConstants.MAX_PAGE_SIZE ? size : BookConstants.DEFAULT_PAGE_SIZE;
    }

    /**
     * 创建空的分页对象
     * <p>
     * 当查询结果为空时，返回一个空的分页对象
     *
     * @param page 页码
     * @param size 每页大小
     * @param <T>  数据类型
     * @return 空的分页对象
     */
    public static <T> IPage<T> emptyPage(int page, int size) {
        return new Page<>(page, size, 0);
    }

    /**
     * 验证并处理分页参数
     * <p>
     * 验证分页参数的有效性，如果无效则返回错误响应，否则返回处理后的有效参数
     *
     * @param page 页码
     * @param size 每页大小
     * @return 验证结果，如果参数无效则包含错误响应，否则包含处理后的有效参数
     */
    public static ValidationResult validateAndProcess(int page, int size) {
        if (!validatePageParams(page, size)) {
            return new ValidationResult(false, ResponseUtil.paramError("分页参数不合法"), page, size);
        }
        
        int validPage = getDefaultPage(page);
        int validSize = getDefaultSize(size);
        return new ValidationResult(true, null, validPage, validSize);
    }
    
    /**
     * 分页参数验证结果类
     */
    public static class ValidationResult {
        private final boolean valid;
        private final R<?> errorResponse;
        private final int page;
        private final int size;
        
        public ValidationResult(boolean valid, R<?> errorResponse, int page, int size) {
            this.valid = valid;
            this.errorResponse = errorResponse;
            this.page = page;
            this.size = size;
        }
        
        public boolean isValid() {
            return valid;
        }
        
        public R<?> getErrorResponse() {
            return errorResponse;
        }
        
        public int getPage() {
            return page;
        }
        
        public int getSize() {
            return size;
        }
    }
}